package com.gitee.wsl.transform.format


internal val c1Digit = charArrayOf(
    '零', '壹', '贰', '叁', '肆', '伍', '陆', '柒',
    '捌', '玖'
)

internal val c2Digit = charArrayOf(
    '零', '一', '二', '三', '四', '五', '六', '七',
    '八', '九'
)

internal val c1Unit = charArrayOf('拾', '佰', '仟')

internal val c2Unit = charArrayOf('十', '百', '千')

internal val chinaUnit = arrayOf("万", "亿", "亿万")

private fun toRMB2(l: Long, cDigit: CharArray, cUnit: CharArray): String {
    var l = l
    var unit = 0
    var bit = 0
    var d: Int
    var hasZero = false
    var sf = false
    val sb = StringBuilder(64)
    while (l > 0) {
        if (bit == 4) {
            if (unit > 2) {
                throw IllegalArgumentException("大写不支持大于一万万亿的数")
            }

            if (sf) {
                if (hasZero || l % 10 == 0L) {
                    sb.append(cDigit[0])
                    hasZero = false
                }
            } else {
                val len: Int = sb.length
                if (len > 0) {
                    sb.deleteAt(len - 1)
                }
            }

            sb.append(chinaUnit[unit])
            unit++
            bit = 0
            sf = false
        }

        d = (l % 10).toInt()
        if (d > 0) {
            sf = true
            if (hasZero) {
                sb.append(cDigit[0])
                hasZero = false
            }
            if (bit != 0) {
                sb.append(cUnit[bit - 1])
            }
            sb.append(cDigit[d])
        } else {
            if (sf) { // 数据尾部的0忽略
                hasZero = true
            }
        }

        bit++
        l /= 10
    }
    return sb.reverse().toString()
}

/**
 * 将浮点数格式成人民币大写方式
 *
 * @param money
 * 浮点数
 * @return 格式化的字符串
 * @exception IllegalArgumentException
 * 当money<0或money>=一万万亿时
 */
internal fun toRMB(money: Double): String {
    return toRMB(money, true, true)
}

internal fun toRMB(money: Double, abbreviate: Boolean, uppercase: Boolean, ): String {
    var money = money
    val cDigit = if (uppercase) c1Digit else c2Digit
    val cUnit = if (uppercase) c1Unit else c2Unit
    val sb = StringBuilder(64)
    if (money < 0) {
        sb.append("负")
        money = -money
    }
    val yuan = money.toLong() // 元

    if (yuan == 0L) {
        sb.append("零")
    } else {
        sb.append(toRMB2(yuan, cDigit, cUnit))
    }
    sb.append('元')

    val jaoFeng = ((money + 0.001 - money.toLong()) * 100).toInt() % 100
    val jao = jaoFeng / 10
    val feng = jaoFeng % 10
    if (jao > 0) {
        sb.append(cDigit[jao])
        sb.append('角')
    }
    if (feng > 0) {
        if (jao == 0) {
            sb.append('零')
        }
        sb.append(cDigit[feng])
        sb.append('分')
    } else {
        sb.append('整')
    }
    return sb.toString()
}

fun toChinese(l: Long, abbreviate: Boolean, uppercase: Boolean ): String {
    var l = l
    var fu = ""

    if (l == 0L) {
        return "零"
    } else if (l < 0) {
        fu = "负"
        l = -l
    }

    val cDigit = if (uppercase) c1Digit else c2Digit
    val cUnit = if (uppercase) c1Unit else c2Unit

    if (abbreviate) {
        return fu + toRMB2(l, cDigit, cUnit).toString()
    } else {
        var sb = StringBuilder(64)
        while (l > 0) {
            val digit = l.toInt() % 10
            sb.append(cDigit[digit])
            l /= 10
        }
        sb = sb.reverse()
        return fu + sb.toString()
    } // if ( abbreviate )
}

fun Format.Companion.RMB( abbreviate: Boolean=false, uppercase: Boolean = true) = DoubleFormat { base-> toRMB(base,abbreviate, uppercase) }

fun Format.Companion.toChinese( abbreviate: Boolean=false, uppercase: Boolean = true): Format<Long>
        = Format{ base-> toChinese(base,abbreviate, uppercase) }